package com.lanchetech.merchant.service.impl;


import com.lanchetech.bean.response.ResultData;
import com.lanchetech.bean.vo.MerchantHomeStatisticsVO;
import com.lanchetech.bean.vo.OrderStatisticAmountVO;
import com.lanchetech.bean.vo.TenantSaleStatisticsVO;
import com.lanchetech.common.enums.AfterSaleStatusEnum;
import com.lanchetech.common.enums.OrdersStatusEnum;
import com.lanchetech.dao.*;
import com.lanchetech.entity.Merchant;
import com.lanchetech.entity.Shop;
import com.lanchetech.entity.ShopAmount;
import com.lanchetech.entity.Tenant;
import com.lanchetech.merchant.service.MerchantService;
import com.lanchetech.merchant.service.WebService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
public class WebServiceImpl implements WebService {

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    AfterSaleMapper afterSaleMapper;

    @Autowired
    OrdersMapper ordersMapper;

    @Autowired
    SpuMapper spuMapper;

    @Autowired
    TenantMapper tenantMapper;

    @Autowired
    ShopStatisticsMapper shopStatisticsMapper;

    public Date getDateStart(Calendar calendar) {
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public Date getDateEnd(Calendar calendar) {
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        return calendar.getTime();
    }

    @Override
    public ResultData<MerchantHomeStatisticsVO> getHomeStatistics() {
        Merchant merchant = (Merchant) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Long tenantId = merchant.getTenantId();
        ValueOperations<String, MerchantHomeStatisticsVO> operations = redisTemplate.opsForValue();
        MerchantHomeStatisticsVO vo = new MerchantHomeStatisticsVO();
        Date date = new Date();//取时间
        Calendar calendar = Calendar.getInstance();

        vo.setShopStatistics(shopStatisticsMapper.findOneByShopId(merchant.getTenantId()));

        if (merchant.getTenantId() != null && merchant.getTenantId() > 0) {
            Tenant tenant = tenantMapper.selectByPrimaryKey(merchant.getTenantId());
            vo.setTenantPoint(tenant.getPoint());
            vo.setWaitToRefund(afterSaleMapper.sumByStatusAndTenantId(AfterSaleStatusEnum.PROCESSING.getStatus(), merchant.getTenantId()));
        }

        // 缓存10分钟的
        String minuteKey = "MerchantHomeStatisticsMinute:" + merchant.getTenantId();
        MerchantHomeStatisticsVO minuteResult = operations.get(minuteKey);
        if (minuteResult != null) {
            return new ResultData<>(minuteResult);
        } else {
            calendar.setTime(date);
            Date todayStart = getDateStart(calendar);
            vo.setTodayOrder(ordersMapper.countByTimeRange(todayStart, date));
            vo.setWaitDelivery(ordersMapper.countByStatusAndLogisticsStatus(OrdersStatusEnum.PAID.getStatus()));
            vo.setAfterSale(afterSaleMapper.countByStatus(AfterSaleStatusEnum.PROCESSING.getStatus()));
            vo.setReturnConfirm(afterSaleMapper.countByStatus(AfterSaleStatusEnum.CONFIRM.getStatus()));
            BigDecimal todayAmount = ordersMapper.sumByTimeRangeAndTenantId(todayStart, date, tenantId);
            vo.setTodayAmount(todayAmount == null ? BigDecimal.ZERO : todayAmount);
            vo.setTodayRefundCount(ordersMapper.countByTimeRangeAndTenantId(todayStart, date, tenantId));

            // 缓存1天的
            String dayKey = "MerchantHomeStatisticsDay:" + merchant.getTenantId();
            MerchantHomeStatisticsVO dayResult = operations.get(dayKey);
            if (dayResult != null) {
                BeanUtils.copyProperties(dayResult, vo, "todayOrder", "waitDelivery", "afterSale", "returnConfirm");
            } else {
                calendar.setTime(date);
                Date todayEnd = getDateEnd(calendar);
                calendar.add(Calendar.DATE, -1);
                Date yesterdayStart = getDateStart(calendar);
                Date yesterdayEnd = getDateEnd(calendar);
                calendar.setTime(date);
                calendar.add(Calendar.DATE, -8);
                vo.setYesterdayOrder(ordersMapper.countByTimeRange(yesterdayStart, yesterdayEnd));
                BigDecimal yesterdayAmount = ordersMapper.sumByTimeRangeAndTenantId(yesterdayStart, yesterdayEnd, tenantId);
                vo.setYesterdayAmount(yesterdayAmount == null ? BigDecimal.ZERO : yesterdayAmount);
                vo.setYesterdayRefundCount(ordersMapper.countByTimeRangeAndTenantId(yesterdayStart, yesterdayEnd, tenantId));
                operations.set(dayKey, vo, todayEnd.getTime() - date.getTime(), TimeUnit.MILLISECONDS);
            }

            operations.set(minuteKey, vo, 10, TimeUnit.MINUTES);
            return new ResultData<>(vo);
        }
    }
}